<template>
  <div>
    <n-grid cols="7">
      <n-grid-item span="1"
        ><n-data-table
          :columns="nodeTableColumns"
          :data="nodeTableData"
          :max-height="250"
          :row-key="rowKey"
          @update-checked-row-keys="handleCheckNodeTable"
      /></n-grid-item>
      <n-grid-item span="2"
        ><div ref="chartAverageRef" :style="{ height, width }"></div
      ></n-grid-item>
      <n-grid-item span="2"><div ref="chartBurstRef" :style="{ height, width }"></div></n-grid-item>
      <n-grid-item span="2"><div ref="chartRatioRef" :style="{ height, width }"></div></n-grid-item>
    </n-grid>
    <n-grid cols="7">
      <n-grid-item span="1"
        ><n-form label-placement="left">
          <n-form-item label="频谱扫描"
            ><n-switch :rail-style="railStyle" v-model:value="isOpenSpectrum"
          /></n-form-item>
          <n-form-item label="监测点"
            ><span>{{ observeNode }}</span></n-form-item
          ></n-form
        ><n-data-table
          :columns="freqTableColumns"
          :data="freqTableData"
          :row-key="freqRowKey"
          :max-height="250"
          @update-checked-row-keys="handleCheckFreqTable"
      /></n-grid-item>
      <n-grid-item span="6">
        <n-grid cols="2">
          <n-grid-item span="1"
            ><div ref="chartAnt1Ref" :style="{ height, width }"></div
          ></n-grid-item>
          <n-grid-item span="1"
            ><div ref="chartAnt2Ref" :style="{ height, width }"></div
          ></n-grid-item> </n-grid
      ></n-grid-item>
    </n-grid>
  </div>
</template>
<script lang="ts" setup>
  import type { DataTableColumns, DataTableRowKey } from 'naive-ui';
  import { getStatusConfig, getRssiStatus, getRssiStatusByIp } from '@/api/status';
  import { getConfigWinthoutCache } from '@/api/config';
  import { ref, onMounted, onBeforeUnmount, computed, toRaw, Ref, watch } from 'vue';
  import type { NodeInfo } from '@/api/status';
  import { useECharts } from '@/hooks/web/useECharts';
  import { basicProps } from './props';
  import { useWebSocket } from '@/hooks/useWebSocket';
  import type { CSSProperties } from 'vue';

  const { isConnected, connect, disconnect, send, addMessageHandler, deleteMessageHandler } =
    useWebSocket(`ws://${window.location.hostname}:3452/`);

  interface RowData {
    key: number;
    id: number;
    node: string;
  }

  interface FreqRowData {
    key: number;
    freq: string;
  }

  interface SpectrumData {
    ident: number; // 消息标识
    id: number; //id
    antIdent: number; //天线序号
    freqId: number; //频率列表id
    guideStrenth: number; //前导部分接收信号强度
    dataStrength: number; //数据部分接收信号强度
    dataBody: number[]; //频谱扫描结果
  }

  const railStyle = ({ focused, checked }: { focused: boolean; checked: boolean }) => {
    const style: CSSProperties = {};
    if (checked) {
      style.background = '#E0531f';
      if (focused) {
        style.boxShadow = '0 0 0 2px #E0531f40';
      }
    } else {
      style.background = 'rgba(0, 0, 0, 0.04)';
      if (focused) {
        style.boxShadow = '0 0 0 2px rgba(0, 0, 0, 0.04)';
      }
    }
    return style;
  };

  // 定时器引用
  const refreshTimer = ref<number | null>(null);
  // 刷新间隔
  const refreshInterval = 5000; // 5秒刷新一次

  const freqList = ref<number[]>([]);

  const nodeInfos = ref<NodeInfo[]>([]);
  const checkNodeInfos = ref<NodeInfo[]>([]);
  const nodeTableData = computed(() => {
    return nodeInfos.value.map((nodeInfo) => ({
      id: nodeInfo.id,
      node: nodeInfo.ip,
    }));
  });
  const rowKey = (row: RowData) => row.id;
  const checkNodeRowKeysRef = ref<DataTableRowKey[]>([]);
  function handleCheckNodeTable(rowKeys: DataTableRowKey[]) {
    checkNodeRowKeysRef.value = rowKeys;
    // console.log(checkNodeRowKeysRef.value);
    checkNodeInfos.value = [
      ...toRaw(nodeInfos.value).filter((node) => checkNodeRowKeysRef.value.includes(node.id)),
    ];
    // console.log(checkNodeInfos);
  }

  const nodeTableColumns: DataTableColumns<RowData> = [
    { type: 'selection' },
    { title: '节点id', key: 'id', width: 70 },
    {
      title: '在线节点',
      key: 'node',
    },
  ];

  /********************************图标*************************************/
  defineProps({
    ...basicProps,
  });
  const rssiStatus = ref<number[][]>([]);
  const chartAverageRef = ref<HTMLDivElement | null>(null);
  const chartBurstRef = ref<HTMLDivElement | null>(null);
  const chartRatioRef = ref<HTMLDivElement | null>(null);
  const { setOptions: setAverageOptions } = useECharts(chartAverageRef as Ref<HTMLDivElement>);
  const { setOptions: setBurstOptions } = useECharts(chartBurstRef as Ref<HTMLDivElement>);
  const { setOptions: setRatioOptions } = useECharts(chartRatioRef as Ref<HTMLDivElement>);

  async function updateChartsData() {
    let xAxisData: number[] = [];
    let averageDataTmp: number[][] = [];
    let burstDataTmp: number[][] = [];
    let ratioDataTmp: number[][] = [];
    let nodeIp: string[] = [];

    for (let i = 0; i < freqList.value.length; ++i) {
      xAxisData.push(freqList.value[i] / 1000000);
    }
    const indices = xAxisData
      .map((value, index) => ({ value, index }))
      .sort((a, b) => a.value - b.value)
      .map((item) => item.index);

    // console.log(checkNodeInfos.value);
    checkNodeInfos.value.sort((a, b) => a.id - b.id);
    for (let i = 0; i < checkNodeInfos.value.length; ++i) {
      const ip = checkNodeInfos.value[i].ip;
      if (!nodeInfos.value.map((nodeInfo) => nodeInfo.ip).includes(ip)) {
        continue;
      }
      const rssi = await getRssiStatusByIp(ip);
      nodeIp.push(ip);

      let averageData: number[] = [];
      let burstData: number[] = [];
      let ratioData: number[] = [];

      for (let i = 0; i < rssi.rssi.length; ++i) {
        averageData.push(rssi.rssi[i][0]);
        burstData.push(rssi.rssi[i][1]);
        ratioData.push(rssi.rssi[i][2]);
      }

      // 排序
      xAxisData.sort((a, b) => a - b);
      averageData = [...indices.map((i) => averageData[i])];
      burstData = [...indices.map((i) => burstData[i])];
      ratioData = [...indices.map((i) => ratioData[i])];

      averageDataTmp.push([...averageData]);
      burstDataTmp.push([...burstData]);
      ratioDataTmp.push([...ratioData]);
    }

    updateAverageCharts(xAxisData, averageDataTmp, nodeIp);
    updateBurstCharts(xAxisData, burstDataTmp, nodeIp);
    updateRatioCharts(xAxisData, ratioDataTmp, nodeIp);
  }

  function updateAverageCharts(xData: number[], sData: number[][], nodeName: string[]) {
    // const min = Math.min(...seriesData.map((subArryay) => Math.min(...subArryay)))
    // const max = Math.max(...seriesData.map((subArray) => Math.max(...subArray)))
    const min = Math.min(...sData.map((arr) => Math.min(...arr)));
    const max = Math.max(...sData.map((arr) => Math.max(...arr)));
    const interval = 0.5; // 固定间隔 0.5

    // 对齐到 0.5 的倍数（确保刻度均匀）
    const alignedMin = Math.floor(min / interval) * interval;
    // const alignedMax = Math.ceil(max / interval) * interval
    let alignedMax = Math.ceil(max / interval) * interval;

    // 动态调整刻度数量（避免过多或过少）
    const range = alignedMax - alignedMin;
    const splitNumber = range <= 1.5 ? 4 : 5;

    // 动态调整间隔
    const dynamicInterval = range !== 0 ? range / (splitNumber - 1) : interval;

    // 防止range为0的情况
    alignedMax = range !== 0 ? alignedMax : alignedMin + dynamicInterval * splitNumber;

    setAverageOptions({
      title: {
        text: 'rssi平均值',
      },
      animation: false, //关闭动画
      xAxis: {
        type: 'category',
        // name: '频点(MHz)',
        position: 'bottom',
        axisLine: {
          onZero: false,
        },
        data: [...xData],
      },
      yAxis: {
        // type: 'value',
        min: alignedMin,
        max: alignedMax,
        interval: dynamicInterval,
        splitNumber: splitNumber,
        axisLabel: {
          formatter: function (value: number) {
            return value.toFixed(1); // 保留一位小数
          },
        },
      },
      tooltip: {
        trigger: 'axis',
        valueFormatter: (value: number) => {
          if (typeof value !== 'number' || isNaN(value)) return '';
          return value.toFixed(1); // 保留 1 位小数
        },
      },
      //   series: [
      //     {
      //       name: '1982.168.147.37',
      //       data: [...sData],
      //       type: 'line',
      //     },
      //   ],
      series: sData.map((arr, index) => ({
        name: nodeName[index],
        data: [...arr],
        type: 'line',
      })),
    });
  }

  function updateBurstCharts(xData: number[], sData: number[][], nodeName: string[]) {
    // const min = Math.min(...seriesData.map((subArryay) => Math.min(...subArryay)))
    // const max = Math.max(...seriesData.map((subArray) => Math.max(...subArray)))
    const min = Math.min(...sData.map((arr) => Math.min(...arr)));
    const max = Math.max(...sData.map((arr) => Math.max(...arr)));
    const interval = 0.5; // 固定间隔 0.5

    // 对齐到 0.5 的倍数（确保刻度均匀）
    const alignedMin = Math.floor(min / interval) * interval;
    // const alignedMax = Math.ceil(max / interval) * interval
    let alignedMax = Math.ceil(max / interval) * interval;

    // 动态调整刻度数量（避免过多或过少）
    const range = alignedMax - alignedMin;
    const splitNumber = range <= 1.5 ? 4 : 5;

    // 动态调整间隔
    const dynamicInterval = range !== 0 ? range / (splitNumber - 1) : interval;

    // 防止range为0的情况
    alignedMax = range !== 0 ? alignedMax : alignedMin + dynamicInterval * splitNumber;

    setBurstOptions({
      title: {
        text: '突发干扰rssi平均值',
      },
      animation: false, //关闭动画
      xAxis: {
        type: 'category',
        position: 'bottom',
        axisLine: {
          onZero: false,
        },
        data: [...xData],
      },
      yAxis: {
        // type: 'value',
        min: alignedMin,
        max: alignedMax,
        interval: dynamicInterval,
        splitNumber: splitNumber,
        axisLabel: {
          formatter: function (value: number) {
            return value.toFixed(1); // 保留一位小数
          },
        },
      },
      tooltip: {
        trigger: 'axis',
        valueFormatter: (value: number) => {
          if (typeof value !== 'number' || isNaN(value)) return '';
          return value.toFixed(1); // 保留 1 位小数
        },
      },
      series: sData.map((arr, index) => ({
        name: nodeName[index],
        data: [...arr],
        type: 'line',
      })),
    });
  }

  function updateRatioCharts(xData: number[], sData: number[][], nodeName: string[]) {
    setRatioOptions({
      title: {
        text: '突发干扰比例(%)',
      },
      animation: false, //关闭动画
      xAxis: {
        type: 'category',
        position: 'bottom',
        axisLine: {
          onZero: false,
        },
        data: [...xData],
      },
      yAxis: {
        type: 'value',
        axisLabel: {
          formatter: function (value: number) {
            return `${(value * 100).toFixed(1)}%`; // 保留一位小数
          },
        },
      },
      tooltip: {
        trigger: 'axis',
        valueFormatter: (value: number) => {
          if (typeof value !== 'number' || isNaN(value)) return '';
          return `${(value * 100).toFixed(1)}%`; // 保留 1 位小数
        },
      },
      series: sData.map((arr, index) => ({
        name: nodeName[index],
        data: [...arr],
        type: 'line',
      })),
    });
  }
  /********************************频谱扫描**********************************/
  // 定时器引用
  const refreshFreqTimer = ref<number | null>(null);
  // 刷新间隔
  const refreshFreqInterval = 5000; // 5秒刷新一次

  const isOpenSpectrum = ref<boolean>(false);
  const observeNode = ref<string>('');
  const freqRowKey = (row: FreqRowData) => row.freq;
  const checkFreqRowKeysRef = ref<DataTableRowKey[]>([]);
  const checkFreq = ref<number[]>([]);
  const freqTableData = computed(() => {
    return freqList.value.map((freq) => ({
      freq: `${freq / 1000000} MHz`,
    }));
  });
  function handleCheckFreqTable(rowKeys: DataTableRowKey[]) {
    checkFreqRowKeysRef.value = rowKeys;
    checkFreq.value = [...checkFreqRowKeysRef.value.map((str) => parseFloat(str))];
    // console.log(checkFreq.value);
  }
  const freqTableColumns: DataTableColumns<FreqRowData> = [
    { type: 'selection' },
    {
      title: '频率',
      key: 'freq',
    },
  ];

  const spanMap = new Map<number, number>([
    [0, 2.5],
    [1, 5],
    [2, 10],
    [3, 20],
    [8, 1.25],
  ]);
  const bandwidth = ref<number>(0);
  const ant1Data = ref<Map<number, Map<number, number>>>(new Map());
  const ant2Data = ref<Map<number, Map<number, number>>>(new Map());

  const chartAnt1Ref = ref<HTMLDivElement | null>(null);
  const chartAnt2Ref = ref<HTMLDivElement | null>(null);
  const { setOptions: setAnt1Options } = useECharts(chartAnt1Ref as Ref<HTMLDivElement>);
  const { setOptions: setAnt2Options } = useECharts(chartAnt2Ref as Ref<HTMLDivElement>);

  function updateSpectrum() {
    const ant1DataTmp: Map<number, Map<number, number>> = new Map();
    const ant2DataTmp: Map<number, Map<number, number>> = new Map();

    for (let i = 0; i < checkFreq.value.length; ++i) {
      const freq = checkFreq.value[i];
      const value1 = ant1Data.value?.get(freq);
      const value2 = ant2Data.value?.get(freq);
      //   console.log('1', ant1Data.value);
      if (value1 !== undefined) {
        ant1DataTmp.set(checkFreq.value[i], value1);
      }
      if (value2 !== undefined) {
        ant2DataTmp.set(checkFreq.value[i], value2);
      }
    }

    // console.log(ant1DataTmp);

    const ant1Keys = Array.from(removeOverlap(ant1DataTmp).keys());
    const ant1Values = Array.from(removeOverlap(ant1DataTmp).values());
    const ant2Values = Array.from(removeOverlap(ant2DataTmp).values());

    // console.log(ant1Keys, ant1Values);

    updateAnt1Charts(ant1Keys, ant1Values);
    updateAnt2Charts(ant1Keys, ant2Values);
  }

  function updateAnt1Charts(keys: number[], data: number[]) {
    setAnt1Options({
      title: {
        text: '天线1频谱',
      },
      animation: false, //关闭动画
      xAxis: {
        type: 'category',
        data: [...keys],
      },
      yAxis: {
        type: 'value',
      },
      series: [
        {
          data: [...data],
          type: 'line',
        },
      ],
      tooltip: {
        trigger: 'axis',
        valueFormatter: (value: number) => {
          if (typeof value !== 'number' || isNaN(value)) return '';
          return value.toFixed(6); // 保留 6 位小数
        },
      },
    });
  }

  function updateAnt2Charts(keys: number[], data: number[]) {
    setAnt2Options({
      title: {
        text: '天线2频谱',
      },
      animation: false, //关闭动画
      xAxis: {
        type: 'category',
        data: [...keys],
      },
      yAxis: {
        type: 'value',
      },
      series: [
        {
          data: [...data],
          type: 'line',
        },
      ],
      tooltip: {
        trigger: 'axis',
        valueFormatter: (value: number) => {
          if (typeof value !== 'number' || isNaN(value)) return '';
          return value.toFixed(6); // 保留 6 位小数
        },
      },
    });
  }

  //频谱去重
  function removeOverlap(data: Map<number, Map<number, number>>): Map<number, number> {
    // 1. 将 Map 转为键值对数组（保持关联）
    // 2. 按键排序（保持键值对应）

    const sortedEntries = Array.from(data.entries()).sort((a, b) => a[0] - b[0]);
    const result: Map<number, number> = new Map();
    let prevEndFreq = -Infinity;
    let lastValidFreq = -Infinity; // 记录最后一个有效频点

    for (const [freq, spectrum] of sortedEntries) {
      const startFreq = freq - (5 * bandwidth.value) / 8;
      const endFreq = freq + (5 * bandwidth.value) / 8;

      // 仅当新数据与旧数据重叠时才清理
      if (startFreq < prevEndFreq) {
        const overlapStart = freq - bandwidth.value / 2 + (bandwidth.value === 40 ? 2 : 0);
        const overlapEnd = prevEndFreq;

        // 仅清理 [overlapStart, overlapEnd] 范围内的旧数据
        for (const key of result.keys()) {
          const keyFreq = parseFloat(key);
          if (keyFreq >= overlapStart && keyFreq <= overlapEnd) {
            result.delete(key);
          }
        }
      }

      // 添加新数据（仅保留有效部分）
      for (const [key, value] of spectrum) {
        const keyFreq = parseFloat(key);
        if (
          keyFreq >= lastValidFreq ||
          keyFreq >= freq - bandwidth.value / 2 + (bandwidth.value === 40 ? 2 : 0)
        ) {
          result.set(key, value);
          lastValidFreq = Math.max(lastValidFreq, keyFreq); // 更新最后一个有效频点
        }
      }

      prevEndFreq = endFreq;
    }

    return result;
  }

  function parseBlobData(blobData: Blob) {
    blobData.arrayBuffer().then((buffer) => {
      //   console.log(buffer);
      if (buffer.byteLength === 4108) {
        const view = new DataView(buffer);

        const result: SpectrumData = {
          ident: 0,
          id: 0,
          antIdent: 0,
          freqId: 0,
          guideStrenth: 0,
          dataStrength: 0,
          dataBody: [],
        };

        //解析头部4个单字节
        result.ident = view.getUint8(0);
        result.id = view.getUint8(1);
        result.antIdent = view.getUint8(2);
        result.freqId = view.getUint8(3);

        // 解析信号强度 2组 共8字节
        result.guideStrenth = view.getFloat32(4, true); // 小端浮点数
        result.dataStrength = view.getFloat32(8, true);

        //解析主题数据(12~4108, 共1024组)
        for (let offset = 12; offset < 4108; offset += 4) {
          result.dataBody.push(10 * Math.log10(view.getFloat32(offset, true)));
        }

        // console.log(result);

        const start = freqList.value[result.freqId] / 1000000 - (5 * bandwidth.value) / 8;
        const offset = (5 * bandwidth.value) / (1024 * 4);
        const tmpSpecSeries: Map<number, number> = new Map();
        for (let i = 0; i < 1024; i++) {
          let key = start + offset * i;
          tmpSpecSeries.set(key, result.dataBody[i]);
        }

        if (result.antIdent === 0) {
          ant1Data.value?.set(freqList.value[result.freqId] / 1000000, tmpSpecSeries);
        } else if (result.antIdent === 1) {
          ant2Data.value?.set(freqList.value[result.freqId] / 1000000, tmpSpecSeries);
        }
      }
    });
  }

  function sendOpenMessage() {
    if (isConnected.value) {
      const data = new Uint8Array([0x00, 0xff, 0x00, 0x02]);
      send(data.buffer);
    }
  }

  watch(isOpenSpectrum, (isOpen) => {
    // console.log(isOpen);
    if (isOpen) {
      connect().then(() => {
        addMessageHandler((data) => {
          //   console.log(data);
          parseBlobData(data);
        });
        sendOpenMessage();
      });
    } else {
      disconnect();
    }
  });

  // 初始化频谱扫描定时器
  function initRefreshFreqTimer() {
    // 立即更新一次
    updateSpectrum();

    refreshFreqTimer.value = window.setInterval(() => {
      //   console.log('111');
      updateSpectrum();
      sendOpenMessage();
    }, refreshFreqInterval);
  }
  // 清除定时器
  function clearRefreshFreqTimer() {
    if (refreshFreqTimer.value) {
      clearInterval(refreshFreqTimer.value);
      refreshFreqTimer.value = null;
    }
  }

  /******************************************************************************************/

  // 初始化定时器
  function initRefreshTimer() {
    // 立即更新一次
    updateNodeInfo();

    refreshTimer.value = window.setInterval(() => {
      //   console.log('111');
      updateNodeInfo();
    }, refreshInterval);
  }
  // 清除定时器
  function clearRefreshTimer() {
    if (refreshTimer.value) {
      clearInterval(refreshTimer.value);
      refreshTimer.value = null;
    }
  }
  // 更新数据
  async function updateNodeInfo() {
    const statusconfig = await getStatusConfig();
    const rssi = await getRssiStatus();
    const config = await getConfigWinthoutCache();
    nodeInfos.value = [...statusconfig.nodeInfos];
    rssiStatus.value = [...rssi.rssi];
    freqList.value = [...config.freqList];
    observeNode.value = config.ip;
    bandwidth.value = spanMap.get(config.span) ?? 0;
    updateChartsData();
  }

  onMounted(async () => {
    // 初始化定时器
    initRefreshTimer();
    initRefreshFreqTimer();
  });

  onBeforeUnmount(() => {
    clearRefreshTimer();
    clearRefreshFreqTimer();
    deleteMessageHandler();
    disconnect();
  });
</script>
